home *** CD-ROM | disk | FTP | other *** search
/ Aminet 40 / Aminet 40 (2000)(Schatztruhe)[!][Dec 2000].iso / Aminet / util / arc / xadmaster.lha / xad / Developer / Sources / clients / LZX.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-08-31  |  24.9 KB  |  955 lines

  1. #ifndef XADMASTER_LZX_C
  2. #define XADMASTER_LZX_C
  3.  
  4. /* Programmheader
  5.  
  6.     Name:        LZX.c
  7.     Main:        xadmaster
  8.     Versionstring:    $VER: LZX.c 1.6 (09.03.2000)
  9.     Author:        SDI, David Tritscher
  10.     Distribution:    Freeware
  11.     Description:    LZX file archiver client
  12.  
  13.  1.0   09.02.99 : first working version
  14.  1.1   13.03.99 : now uses register parameters
  15.  1.2   20.06.99 : removed exec.library calls
  16.  1.3   29.06.99 : now uses master free stuff
  17.  1.4   29.08.99 : uses ConvertE.c instead of own routines and
  18.     uses crc copy function
  19.  1.5   02.01.00 : now library version 4 client
  20.  1.6   09.03.00 : now library version 6 client
  21. */
  22.  
  23. /* The decrunch routines of this client are based on unlzx sources code made
  24.    by David Tritscher. Thanks guy, was a big help. I made the routines
  25.    reentrant (using a parameter structure) and developed the XAD interface
  26.    functions. */
  27.  
  28. #include <proto/xadmaster.h>
  29. #include <exec/memory.h>
  30. #include <dos/dos.h>
  31. #include "SDI_compiler.h"
  32. #define SDI_TO_ANSI
  33. #include "SDI_ASM_STD_protos.h"
  34. #include "ConvertE.c"
  35.  
  36. #ifndef XADMASTERFILE
  37. #define LZX_Client        FirstClient
  38. #define NEXTCLIENT        0
  39. #define XADMASTERVERSION    8
  40. UBYTE version[] = "$VER: LZX 1.6 (09.03.2000) Freeware";
  41. #endif
  42. #define LZX_VERSION        1
  43. #define LZX_REVISION        6
  44.  
  45. /* ---------------------------------------------------------------------- */
  46.  
  47. #define LZXINFO_DAMAGE_PROTECT 1
  48. #define LZXINFO_FLAG_LOCKED 2
  49.  
  50. struct LZXInfo_Header
  51. {
  52.   UBYTE ID[3];            /* "LZX" */
  53.   UBYTE Flags;            /* LZXINFO_FLAG_#? */
  54.   UBYTE Unknown[6];        
  55. };
  56.  
  57. #define LZXHDR_FLAG_MERGED    (1<<0)
  58.  
  59. #define LZXHDR_PROT_READ    (1<<0)
  60. #define LZXHDR_PROT_WRITE    (1<<1)
  61. #define LZXHDR_PROT_DELETE    (1<<2)
  62. #define LZXHDR_PROT_EXECUTE    (1<<3)
  63. #define LZXHDR_PROT_ARCHIVE    (1<<4)
  64. #define LZXHDR_PROT_HOLD    (1<<5)
  65. #define LZXHDR_PROT_SCRIPT    (1<<6)
  66. #define LZXHDR_PROT_PURE    (1<<7)
  67.  
  68. #define LZXHDR_TYPE_MSDOS    0
  69. #define LZXHDR_TYPE_WINDOWS    1
  70. #define LZXHDR_TYPE_OS2        2
  71. #define LZXHDR_TYPE_AMIGA    10
  72. #define LZXHDR_TYPE_UNIX    20
  73.  
  74. #define LZXHDR_PACK_STORE    0
  75. #define LZXHDR_PACK_NORMAL    2
  76. #define LZXHDR_PACK_EOF        32
  77.  
  78. struct LZXArc_Header
  79. {
  80.   UBYTE Attributes;        /*  0 - LZXHDR_PROT_#? */
  81.   UBYTE pad1;            /*  1 */
  82.   ULONG FileSize;        /*  2 (little endian) */
  83.   ULONG CrSize;            /*  6 (little endian) */
  84.   UBYTE MachineType;        /* 10 - LZXHDR_TYPE_#? */
  85.   UBYTE PackMode;        /* 11 - LZXHDR_PACK_#? */
  86.   UBYTE Flags;            /* 12 - LZXHDR_FLAG_#? */
  87.   UBYTE pad2;            /* 13 */
  88.   UBYTE CommentSize;        /* 14 - length (0-79) */
  89.   UBYTE ExtractVersion;        /* 15 - version needed to extract */
  90.   UBYTE pad3;            /* 16 */
  91.   UBYTE pad4;            /* 17 */
  92.   ULONG Date;            /* 18 - Packed_Date */
  93.   ULONG DataCRC;        /* 22 (little endian) */
  94.   ULONG HeaderCRC;        /* 26 (little endian) */
  95.   UBYTE FilenameSize;        /* 30 - filename length */
  96. }; /* SIZE = 31 */
  97.  
  98. /* Header CRC includes filename and comment. */
  99.  
  100. #define LZXHEADERSIZE    31
  101.  
  102. /* Packed date [4 BYTES, bit 0 is MSB, 31 is LSB]
  103.   bit  0 -  4    Day
  104.        5 -  8    Month    (January is 0)
  105.        9 - 14    Year    (start 1970)
  106.       15 - 19    Hour
  107.       20 - 25    Minute
  108.       26 - 31    Second
  109. */
  110.  
  111. struct LZXEntryData {
  112.   ULONG CRC;        /* CRC of uncrunched data */
  113.   ULONG PackMode;    /* CrunchMode */
  114.   ULONG ArchivePos;    /* Position is source file */
  115.   ULONG DataStart;    /* Position in merged buffer */
  116. };
  117.  
  118. #define LZXPE(a)    ((struct LZXEntryData *) ((a)->xfi_PrivateInfo))
  119. #define LZXDD(a)    ((struct LZXDecrData *) ((a)->xai_PrivateClient))
  120. struct LZXDecrData {
  121.   ULONG ArchivePos;    /* The Archive-Pos to detect if it is correct buffer */
  122.   ULONG DataPos;    /* must be lower or equal to current entry or reinit is necessary */
  123.  
  124.   UBYTE *source;
  125.   UBYTE *destination;
  126.   UBYTE *source_end;
  127.   UBYTE *destination_end;
  128.   UBYTE *pos;
  129.  
  130.   ULONG decrunch_method;
  131.   ULONG decrunch_length;
  132.   ULONG pack_size;
  133.   ULONG last_offset;
  134.   ULONG control;
  135.   LONG  shift;
  136.  
  137.   UBYTE offset_len[8];
  138.   UWORD offset_table[128];
  139.   UBYTE huffman20_len[20];
  140.   UWORD huffman20_table[96];
  141.   UBYTE literal_len[768];
  142.   UWORD literal_table[5120];
  143.  
  144.   UBYTE read_buffer[16384];        /* have a reasonable sized read buffer */
  145.   UBYTE decrunch_buffer[258+65536+258];    /* allow overrun for speed */
  146. };
  147.  
  148. ASM(BOOL) LZX_RecogData(REG(d0, ULONG size), REG(a0, STRPTR data),
  149. REG(a6, struct xadMasterBase *xadMasterBase))
  150. {
  151.   if(data[0] == 'L' && data[1] == 'Z' && data[2] == 'X')
  152.     return 1;
  153.   else
  154.     return 0;
  155. }
  156.  
  157. ASM(LONG) LZX_GetInfo(REG(a0, struct xadArchiveInfo *ai),
  158. REG(a6, struct xadMasterBase *xadMasterBase))
  159. {
  160.   LONG err, num = 1;
  161.   ULONG bufpos = 0;
  162.   struct xadFileInfo *fi = 0, *fi2, *fig = 0; /* fig - first grouped ptr */
  163.   struct LZXArc_Header head;
  164.  
  165.   if(!(err = xadHookAccess(XADAC_INPUTSEEK, sizeof(struct LZXInfo_Header), 0, ai)))
  166.   {
  167.     while(!err && ai->xai_InPos < ai->xai_InSize)
  168.     {
  169.       if(!(err = xadHookAccess(XADAC_READ, LZXHEADERSIZE, &head, ai)))
  170.       {
  171.     ULONG i, j, k, l, crc;
  172.         i = head.CommentSize;
  173.         j = head.FilenameSize;
  174.         k = EndConvI32(head.HeaderCRC);
  175.         head.HeaderCRC = 0; /* clear for CRC check */
  176.  
  177.         if(!(fi2 = (struct xadFileInfo *) xadAllocObject(XADOBJ_FILEINFO,
  178.         XAD_OBJNAMESIZE, j+1, i ? XAD_OBJCOMMENTSIZE : TAG_IGNORE, i+1,
  179.         XAD_OBJPRIVINFOSIZE, sizeof(struct LZXEntryData), TAG_DONE)))
  180.           err = XADERR_NOMEMORY;
  181.         else if(!(err = xadHookAccess(XADAC_READ, j, fi2->xfi_FileName, ai)) &&
  182.         (!i || !(err = xadHookAccess(XADAC_READ, i, fi2->xfi_Comment, ai))))
  183.         {
  184.           l = EndConvI32(head.CrSize);
  185.  
  186.           if(!l || !(err = xadHookAccess(XADAC_INPUTSEEK, l, 0, ai)))
  187.           {
  188.             crc = xadCalcCRC32(XADCRC32_ID1, ~0, LZXHEADERSIZE, (STRPTR) &head);
  189.             crc = xadCalcCRC32(XADCRC32_ID1, crc, j, fi2->xfi_FileName);
  190.             if(i)
  191.               crc = xadCalcCRC32(XADCRC32_ID1, crc, i, fi2->xfi_Comment);
  192.  
  193.             if(~crc != k)
  194.               err = XADERR_CHECKSUM;
  195.             else
  196.             {
  197.               if(!fig)
  198.               {
  199.                 fig = fi2; bufpos = 0;
  200.               }
  201.           fi2->xfi_Size = EndConvI32(head.FileSize);
  202.           fi2->xfi_EntryNumber = num++;
  203.           if(!l && !fi2->xfi_Size && fi2->xfi_FileName[--j] == '/')
  204.           {
  205.             fi2->xfi_FileName[j] = 0;
  206.             fi2->xfi_Flags |= XADFIF_DIRECTORY;
  207.           }
  208.  
  209.           i = head.Attributes;
  210.           j = 0;
  211.  
  212.           if(!(i & LZXHDR_PROT_READ))
  213.             j |= FIBF_READ;
  214.           if(!(i & LZXHDR_PROT_WRITE))
  215.             j |= FIBF_WRITE;
  216.           if(!(i & LZXHDR_PROT_DELETE))
  217.             j |= FIBF_DELETE;
  218.           if(!(i & LZXHDR_PROT_EXECUTE))
  219.             j |= FIBF_EXECUTE;
  220.           j |= (i & (LZXHDR_PROT_ARCHIVE|LZXHDR_PROT_SCRIPT));
  221.           if(i & LZXHDR_PROT_PURE)
  222.             j |= FIBF_PURE;
  223.           if(i & LZXHDR_PROT_HOLD)
  224.             j |= (1<<7);    /* not defined in <dos/dos.h> */
  225.           fi2->xfi_Protection = j;
  226.  
  227.           { /* Make the date */
  228.             struct xadDate d;
  229.             j = head.Date;
  230.             d.xd_Second = j & 63;
  231.             j >>= 6;
  232.             d.xd_Minute = j & 63;
  233.             j >>= 6;
  234.             d.xd_Hour = j & 31;
  235.             j >>= 5;
  236.             d.xd_Year = 1970 + (j & 63);
  237.             j >>= 6;
  238.             d.xd_Month = 1 + (j & 15);
  239.             j >>= 4;
  240.             d.xd_Day = j;
  241.             d.xd_Micros = 0;
  242.                 xadConvertDates(XAD_DATEXADDATE, &d, XAD_GETDATEXADDATE,
  243.                 &fi2->xfi_Date, TAG_DONE);
  244.           }
  245.           LZXPE(fi2)->CRC = EndConvI32(head.DataCRC);
  246.           LZXPE(fi2)->DataStart = bufpos;
  247.           bufpos += fi2->xfi_Size;
  248.           if(head.Flags & LZXHDR_FLAG_MERGED)
  249.           {
  250.             fi2->xfi_Flags |= XADFIF_GROUPED;
  251.             if(l)
  252.             {
  253.               fi2->xfi_Flags |= XADFIF_ENDOFGROUP;
  254.               fi2->xfi_GroupCrSize = l;
  255.             }
  256.           }
  257.           else
  258.             fi2->xfi_CrunchSize = l;
  259.           
  260.           if(l)
  261.           {
  262.             LZXPE(fi2)->ArchivePos = ai->xai_InPos-l;
  263.             LZXPE(fi2)->PackMode = head.PackMode;
  264.             while(fig)
  265.             {
  266.               fig->xfi_GroupCrSize = l;
  267.               LZXPE(fig)->ArchivePos = ai->xai_InPos-l;
  268.               LZXPE(fig)->PackMode = head.PackMode;
  269.                   fig = fig->xfi_Next;
  270.                 }
  271.               }
  272.  
  273.               if(!fi)
  274.                 ai->xai_FileInfo = fi2;
  275.               else
  276.                 fi->xfi_Next = fi2;
  277.               fi = fi2;
  278.               fi2 = 0;
  279.             } /* skip crunched data */
  280.           } /* get filename and comment */
  281.           if(fi2)
  282.             xadFreeObjectA(fi2,0);
  283.         } /* xadFileInfo Allocation */
  284.       } /* READ header */
  285.     } /* while loop */
  286.   } /* INPUTSEEK 3 bytes */
  287.  
  288.   if(err && ai->xai_FileInfo)
  289.   {
  290.     ai->xai_Flags |= XADAIF_FILECORRUPT;
  291.     ai->xai_LastError = err;
  292.     err = 0;
  293.   }
  294.  
  295.   return err;
  296. }
  297.  
  298. /* ---------------------------------------------------------------------- */
  299.  
  300. static const UBYTE LZXtable_one[32] = {
  301.   0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13,14,14
  302. };
  303.  
  304. static const ULONG LZXtable_two[32] = {
  305.   0,1,2,3,4,6,8,12,16,24,32,48,64,96,128,192,256,384,512,768,1024,
  306.   1536,2048,3072,4096,6144,8192,12288,16384,24576,32768,49152,
  307. };
  308.  
  309. static const UWORD LZXmask_bits[16] = {
  310.   0x0000,0x0001,0x0003,0x0007,0x000F,0x001F,0x003F,0x007F,
  311.   0x00FF,0x01FF,0x03FF,0x07FF,0x0FFF,0x1FFF,0x3FFF,0x7FFF,
  312. };
  313.  
  314. static const UBYTE LZXtable_four[34] = {
  315.   0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,
  316.   0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16
  317. };
  318.  
  319. /* ---------------------------------------------------------------------- */
  320.  
  321. /* Build a fast huffman decode table from the symbol bit lengths.         */
  322. /* There is an alternate algorithm which is faster but also more complex. */
  323.  
  324. static LONG LZXmake_decode_table(LONG number_symbols, LONG LZXtable_size,
  325.                       UBYTE *length, unsigned short *table)
  326. {
  327.  register UBYTE bit_num = 0;
  328.  register LONG symbol;
  329.  ULONG leaf; /* could be a register */
  330.  ULONG LZXtable_mask, bit_mask, pos, fill, next_symbol, reverse;
  331.  LONG abort = 0;
  332.  
  333.  pos = 0; /* consistantly used as the current position in the decode table */
  334.  
  335.  bit_mask = LZXtable_mask = 1 << LZXtable_size;
  336.  
  337.  bit_mask >>= 1; /* don't do the first number */
  338.  bit_num++;
  339.  
  340.  while((!abort) && (bit_num <= LZXtable_size))
  341.  {
  342.   for(symbol = 0; symbol < number_symbols; symbol++)
  343.   {
  344.    if(length[symbol] == bit_num)
  345.    {
  346.     reverse = pos; /* reverse the order of the position's bits */
  347.     leaf = 0;
  348.     fill = LZXtable_size;
  349.     do /* reverse the position */
  350.     {
  351.      leaf = (leaf << 1) + (reverse & 1);
  352.      reverse >>= 1;
  353.     } while(--fill);
  354.     if((pos += bit_mask) > LZXtable_mask)
  355.     {
  356.      abort = 1;
  357.      break; /* we will overrun the table! abort! */
  358.     }
  359.     fill = bit_mask;
  360.     next_symbol = 1 << bit_num;
  361.     do
  362.     {
  363.      table[leaf] = symbol;
  364.      leaf += next_symbol;
  365.     } while(--fill);
  366.    }
  367.   }
  368.   bit_mask >>= 1;
  369.   bit_num++;
  370.  }
  371.  
  372.  if((!abort) && (pos != LZXtable_mask))
  373.  {
  374.   for(symbol = pos; symbol < LZXtable_mask; symbol++) /* clear the rest of the table */
  375.   {
  376.    reverse = symbol; /* reverse the order of the position's bits */
  377.    leaf = 0;
  378.    fill = LZXtable_size;
  379.    do /* reverse the position */
  380.    {
  381.     leaf = (leaf << 1) + (reverse & 1);
  382.     reverse >>= 1;
  383.    } while(--fill);
  384.    table[leaf] = 0;
  385.   }
  386.   next_symbol = LZXtable_mask >> 1;
  387.   pos <<= 16;
  388.   LZXtable_mask <<= 16;
  389.   bit_mask = 32768;
  390.  
  391.   while((!abort) && (bit_num <= 16))
  392.   {
  393.    for(symbol = 0; symbol < number_symbols; symbol++)
  394.    {
  395.     if(length[symbol] == bit_num)
  396.     {
  397.      reverse = pos >> 16; /* reverse the order of the position's bits */
  398.      leaf = 0;
  399.      fill = LZXtable_size;
  400.      do /* reverse the position */
  401.      {
  402.       leaf = (leaf << 1) + (reverse & 1);
  403.       reverse >>= 1;
  404.      } while(--fill);
  405.      for(fill = 0; fill < bit_num - LZXtable_size; fill++)
  406.      {
  407.       if(table[leaf] == 0)
  408.       {
  409.        table[(next_symbol << 1)] = 0;
  410.        table[(next_symbol << 1) + 1] = 0;
  411.        table[leaf] = next_symbol++;
  412.       }
  413.       leaf = table[leaf] << 1;
  414.       leaf += (pos >> (15 - fill)) & 1;
  415.      }
  416.      table[leaf] = symbol;
  417.      if((pos += bit_mask) > LZXtable_mask)
  418.      {
  419.       abort = 1;
  420.       break; /* we will overrun the table! abort! */
  421.      }
  422.     }
  423.    }
  424.    bit_mask >>= 1;
  425.    bit_num++;
  426.   }
  427.  }
  428.  if(pos != LZXtable_mask) abort = 1; /* the table is incomplete! */
  429.  
  430.  return(abort);
  431. }
  432.  
  433. /* ---------------------------------------------------------------------- */
  434. /* Read and build the decrunch tables. There better be enough data in the */
  435. /* source buffer or it's stuffed. */
  436.  
  437. static LONG LZX_read_literal_table(struct LZXDecrData *decr)
  438. {
  439.  register ULONG control;
  440.  register LONG shift;
  441.  ULONG temp; /* could be a register */
  442.  ULONG symbol, pos, count, fix, max_symbol;
  443.  UBYTE *source;
  444.  LONG abort = 0;
  445.  
  446.  source = decr->source;
  447.  control = decr->control;
  448.  shift = decr->shift;
  449.  
  450.  if(shift < 0) /* fix the control word if necessary */
  451.  {
  452.   shift += 16;
  453.   control += *source++ << (8 + shift);
  454.   control += *source++ << shift;
  455.  }
  456.  
  457. /* read the decrunch method */
  458.  
  459.  decr->decrunch_method = control & 7;
  460.  control >>= 3;
  461.  if((shift -= 3) < 0)
  462.  {
  463.   shift += 16;
  464.   control += *source++ << (8 + shift);
  465.   control += *source++ << shift;
  466.  }
  467.  
  468. /* Read and build the offset huffman table */
  469.  
  470.  if((!abort) && (decr->decrunch_method == 3))
  471.  {
  472.   for(temp = 0; temp < 8; temp++)
  473.   {
  474.    decr->offset_len[temp] = control & 7;
  475.    control >>= 3;
  476.    if((shift -= 3) < 0)
  477.    {
  478.     shift += 16;
  479.     control += *source++ << (8 + shift);
  480.     control += *source++ << shift;
  481.    }
  482.   }
  483.   abort = LZXmake_decode_table(8, 7, decr->offset_len, decr->offset_table);
  484.  }
  485.  
  486. /* read decrunch length */
  487.  
  488.  if(!abort)
  489.  {
  490.   decr->decrunch_length = (control & 255) << 16;
  491.   control >>= 8;
  492.   if((shift -= 8) < 0)
  493.   {
  494.    shift += 16;
  495.    control += *source++ << (8 + shift);
  496.    control += *source++ << shift;
  497.   }
  498.   decr->decrunch_length += (control & 255) << 8;
  499.   control >>= 8;
  500.   if((shift -= 8) < 0)
  501.   {
  502.    shift += 16;
  503.    control += *source++ << (8 + shift);
  504.    control += *source++ << shift;
  505.   }
  506.   decr->decrunch_length += (control & 255);
  507.   control >>= 8;
  508.   if((shift -= 8) < 0)
  509.   {
  510.    shift += 16;
  511.    control += *source++ << (8 + shift);
  512.    control += *source++ << shift;
  513.   }
  514.  }
  515.  
  516. /* read and build the huffman literal table */
  517.  
  518.  if((!abort) && (decr->decrunch_method != 1))
  519.  {
  520.   pos = 0;
  521.   fix = 1;
  522.   max_symbol = 256;
  523.  
  524.   do
  525.   {
  526.    for(temp = 0; temp < 20; temp++)
  527.    {
  528.     decr->huffman20_len[temp] = control & 15;
  529.     control >>= 4;
  530.     if((shift -= 4) < 0)
  531.     {
  532.      shift += 16;
  533.      control += *source++ << (8 + shift);
  534.      control += *source++ << shift;
  535.     }
  536.    }
  537.    abort = LZXmake_decode_table(20, 6, decr->huffman20_len, decr->huffman20_table);
  538.  
  539.    if(abort) break; /* argh! table is corrupt! */
  540.  
  541.    do
  542.    {
  543.     if((symbol = decr->huffman20_table[control & 63]) >= 20)
  544.     {
  545.      do /* symbol is longer than 6 bits */
  546.      {
  547.       symbol = decr->huffman20_table[((control >> 6) & 1) + (symbol << 1)];
  548.       if(!shift--)
  549.       {
  550.        shift += 16;
  551.        control += *source++ << 24;
  552.        control += *source++ << 16;
  553.       }
  554.       control >>= 1;
  555.      } while(symbol >= 20);
  556.      temp = 6;
  557.     }
  558.     else
  559.     {
  560.      temp = decr->huffman20_len[symbol];
  561.     }
  562.     control >>= temp;
  563.     if((shift -= temp) < 0)
  564.     {
  565.      shift += 16;
  566.      control += *source++ << (8 + shift);
  567.      control += *source++ << shift;
  568.     }
  569.     switch(symbol)
  570.     {
  571.      case 17:
  572.      case 18:
  573.      {
  574.       if(symbol == 17)
  575.       {
  576.        temp = 4;
  577.        count = 3;
  578.       }
  579.       else /* symbol == 18 */
  580.       {
  581.        temp = 6 - fix;
  582.        count = 19;
  583.       }
  584.       count += (control & LZXmask_bits[temp]) + fix;
  585.       control >>= temp;
  586.       if((shift -= temp) < 0)
  587.       {
  588.        shift += 16;
  589.        control += *source++ << (8 + shift);
  590.        control += *source++ << shift;
  591.       }
  592.       while((pos < max_symbol) && (count--))
  593.        decr->literal_len[pos++] = 0;
  594.       break;
  595.      }
  596.      case 19:
  597.      {
  598.       count = (control & 1) + 3 + fix;
  599.       if(!shift--)
  600.       {
  601.        shift += 16;
  602.        control += *source++ << 24;
  603.        control += *source++ << 16;
  604.       }
  605.       control >>= 1;
  606.       if((symbol = decr->huffman20_table[control & 63]) >= 20)
  607.       {
  608.        do /* symbol is longer than 6 bits */
  609.        {
  610.         symbol = decr->huffman20_table[((control >> 6) & 1) + (symbol << 1)];
  611.         if(!shift--)
  612.         {
  613.          shift += 16;
  614.          control += *source++ << 24;
  615.          control += *source++ << 16;
  616.         }
  617.         control >>= 1;
  618.        } while(symbol >= 20);
  619.        temp = 6;
  620.       }
  621.       else
  622.       {
  623.        temp = decr->huffman20_len[symbol];
  624.       }
  625.       control >>= temp;
  626.       if((shift -= temp) < 0)
  627.       {
  628.        shift += 16;
  629.        control += *source++ << (8 + shift);
  630.        control += *source++ << shift;
  631.       }
  632.       symbol = LZXtable_four[decr->literal_len[pos] + 17 - symbol];
  633.       while((pos < max_symbol) && (count--))
  634.        decr->literal_len[pos++] = symbol;
  635.       break;
  636.      }
  637.      default:
  638.      {
  639.       symbol = LZXtable_four[decr->literal_len[pos] + 17 - symbol];
  640.       decr->literal_len[pos++] = symbol;
  641.       break;
  642.      }
  643.     }
  644.    } while(pos < max_symbol);
  645.    fix--;
  646.    max_symbol += 512;
  647.   } while(max_symbol == 768);
  648.  
  649.   if(!abort)
  650.    abort = LZXmake_decode_table(768, 12, decr->literal_len, decr->literal_table);
  651.  }
  652.  
  653.  decr->control = control;
  654.  decr->shift = shift;
  655.  decr->source = source;
  656.  return(abort);
  657. }
  658.  
  659. /* ---------------------------------------------------------------------- */
  660.  
  661. /* Fill up the decrunch buffer. Needs lots of overrun for both destination */
  662. /* and source buffers. Most of the time is spent in this routine so it's  */
  663. /* pretty damn optimized. */
  664. static void LZXdecrunch(struct LZXDecrData *decr)
  665. {
  666.  register ULONG control;
  667.  register LONG shift;
  668.  ULONG temp; /* could be a register */
  669.  ULONG symbol, count;
  670.  UBYTE *string, *source, *destination;
  671.  
  672.  control = decr->control;
  673.  shift = decr->shift;
  674.  source = decr->source;
  675.  destination = decr->destination;
  676.  
  677.  do
  678.  {
  679.   if((symbol = decr->literal_table[control & 4095]) >= 768)
  680.   {
  681.    control >>= 12;
  682.    if((shift -= 12) < 0)
  683.    {
  684.     shift += 16;
  685.     control += *source++ << (8 + shift);
  686.     control += *source++ << shift;
  687.    }
  688.    do /* literal is longer than 12 bits */
  689.    {
  690.     symbol = decr->literal_table[(control & 1) + (symbol << 1)];
  691.     if(!shift--)
  692.     {
  693.      shift += 16;
  694.      control += *source++ << 24;
  695.      control += *source++ << 16;
  696.     }
  697.     control >>= 1;
  698.    } while(symbol >= 768);
  699.   }
  700.   else
  701.   {
  702.    temp = decr->literal_len[symbol];
  703.    control >>= temp;
  704.    if((shift -= temp) < 0)
  705.    {
  706.     shift += 16;
  707.     control += *source++ << (8 + shift);
  708.     control += *source++ << shift;
  709.    }
  710.   }
  711.   if(symbol < 256)
  712.   {
  713.    *destination++ = symbol;
  714.   }
  715.   else
  716.   {
  717.    symbol -= 256;
  718.    count = LZXtable_two[temp = symbol & 31];
  719.    temp = LZXtable_one[temp];
  720.    if((temp >= 3) && (decr->decrunch_method == 3))
  721.    {
  722.     temp -= 3;
  723.     count += ((control & LZXmask_bits[temp]) << 3);
  724.     control >>= temp;
  725.     if((shift -= temp) < 0)
  726.     {
  727.      shift += 16;
  728.      control += *source++ << (8 + shift);
  729.      control += *source++ << shift;
  730.     }
  731.     count += (temp = decr->offset_table[control & 127]);
  732.     temp = decr->offset_len[temp];
  733.    }
  734.    else
  735.    {
  736.     count += control & LZXmask_bits[temp];
  737.     if(!count) count = decr->last_offset;
  738.    }
  739.    control >>= temp;
  740.    if((shift -= temp) < 0)
  741.    {
  742.     shift += 16;
  743.     control += *source++ << (8 + shift);
  744.     control += *source++ << shift;
  745.    }
  746.    decr->last_offset = count;
  747.  
  748.    count = LZXtable_two[temp = (symbol >> 5) & 15] + 3;
  749.    temp = LZXtable_one[temp];
  750.    count += (control & LZXmask_bits[temp]);
  751.    control >>= temp;
  752.    if((shift -= temp) < 0)
  753.    {
  754.     shift += 16;
  755.     control += *source++ << (8 + shift);
  756.     control += *source++ << shift;
  757.    }
  758.    string = (decr->decrunch_buffer + decr->last_offset < destination) ?
  759.             destination - decr->last_offset : destination + 65536 - decr->last_offset;
  760.    do
  761.    {
  762.     *destination++ = *string++;
  763.    } while(--count);
  764.   }
  765.  } while((destination < decr->destination_end) && (source < decr->source_end));
  766.  
  767.  decr->control = control;
  768.  decr->shift = shift;
  769.  decr->source = source;
  770.  decr->destination = destination;
  771. }
  772.  
  773. /* ---------------------------------------------------------------------- */
  774.  
  775. static LONG LZXextract(struct xadArchiveInfo *ai, struct xadMasterBase *xadMasterBase,
  776. ULONG unpack_size, ULONG rescrc)
  777. {
  778.   UBYTE *temp;
  779.   ULONG count, crc = ~0;
  780.   LONG err;
  781.   struct LZXDecrData *decr;
  782.  
  783.   decr = (struct LZXDecrData *) ai->xai_PrivateClient;
  784.  
  785.   while(unpack_size > 0)
  786.   {
  787.     if(decr->pos == decr->destination) /* time to fill the buffer? */
  788.     {
  789.       /* check if we have enough data and read some if not */
  790.       if(decr->source >= decr->source_end) /* have we exhausted the current read buffer? */
  791.       {
  792.         temp = decr->read_buffer;
  793.         if((count = temp - decr->source + 16384))
  794.         {
  795.           do /* copy the remaining overrun to the start of the buffer */
  796.           {
  797.             *temp++ = *(decr->source++);
  798.           } while(--count);
  799.         }
  800.         decr->source = decr->read_buffer;
  801.         count = decr->source - temp + 16384;
  802.  
  803.         if(decr->pack_size < count)
  804.           count = decr->pack_size; /* make sure we don't read too much */
  805.  
  806.         if((err = xadHookAccess(XADAC_READ, count, temp, ai)))
  807.           return err;
  808.         decr->pack_size -= count;
  809.  
  810.         temp += count;
  811.         if(decr->source >= temp)
  812.           return XADERR_DECRUNCH; /* argh! no more data! */
  813.       } /* if(decr->source >= decr->source_end) */
  814.  
  815.     /* check if we need to read the tables */
  816.     if(decr->decrunch_length <= 0)
  817.     {
  818.       if(LZX_read_literal_table(decr))
  819.         return XADERR_DECRUNCH; /* argh! can't make huffman tables! */
  820.     }
  821.  
  822.     /* unpack some data */
  823.     if(decr->destination >= decr->decrunch_buffer + 258 + 65536)
  824.     {
  825.       if((count = decr->destination - decr->decrunch_buffer - 65536))
  826.       {
  827.         temp = (decr->destination = decr->decrunch_buffer) + 65536;
  828.         do /* copy the overrun to the start of the buffer */
  829.         {
  830.           *(decr->destination++) = *temp++;
  831.         } while(--count);
  832.       }
  833.       decr->pos = decr->destination;
  834.     }
  835.     decr->destination_end = decr->destination + decr->decrunch_length;
  836.     if(decr->destination_end > decr->decrunch_buffer + 258 + 65536)
  837.       decr->destination_end = decr->decrunch_buffer + 258 + 65536;
  838.     temp = decr->destination;
  839.  
  840.     LZXdecrunch(decr);
  841.  
  842.     decr->decrunch_length -= (decr->destination - temp);
  843.    }
  844.  
  845. /* calculate amount of data we can use before we need to fill the buffer again */
  846.    count = decr->destination - decr->pos;
  847.    if(count > unpack_size)
  848.      count = unpack_size; /* take only what we need */
  849.  
  850.    if(rescrc) /* when no CRC given, then skip writing */
  851.    {
  852.      crc = xadCalcCRC32(XADCRC32_ID1, crc, count, decr->pos);
  853.      if((err = xadHookAccess(XADAC_WRITE, count, decr->pos, ai)))
  854.        return err;
  855.    }
  856.    unpack_size -= count;
  857.    decr->pos += count;
  858.    decr->DataPos += count;
  859.  }
  860.  
  861.  if(rescrc && ~crc != rescrc)
  862.    return XADERR_CHECKSUM;
  863.  
  864.  return 0;
  865. }
  866.  
  867. /* ---------------------------------------------------------------------- */
  868.  
  869. ASM(LONG) LZX_UnArchive(REG(a0, struct xadArchiveInfo *ai),
  870. REG(a6, struct xadMasterBase *xadMasterBase))
  871. {
  872.   struct xadFileInfo *fi;
  873.   struct LZXDecrData *decr = 0;
  874.   LONG ret = 0, i;
  875.   ULONG crc = ~0;
  876.  
  877.   fi = ai->xai_CurFile;
  878.   if(!ai->xai_PrivateClient || LZXDD(ai)->ArchivePos != LZXPE(fi)->ArchivePos
  879.   || LZXDD(ai)->DataPos > LZXPE(fi)->DataStart)
  880.   {
  881.     if(ai->xai_PrivateClient) /* free the unneeded data */
  882.     {
  883.       xadFreeObjectA(ai->xai_PrivateClient, 0);
  884.       ai->xai_PrivateClient = 0;
  885.     }
  886.     if((i = LZXPE(fi)->ArchivePos - ai->xai_InPos))
  887.     {
  888.       if((ret = xadHookAccess(XADAC_INPUTSEEK, i, 0, ai)))
  889.         return ret;
  890.     }
  891.   }
  892.  
  893.   switch(LZXPE(fi)->PackMode)
  894.   {
  895.   case LZXHDR_PACK_STORE:
  896.     if(!(ret = xadHookTagAccess(XADAC_COPY, fi->xfi_Size, 0, ai, XAD_GETCRC32, &crc, TAG_DONE)) && ~crc != LZXPE(fi)->CRC)
  897.       ret = XADERR_CHECKSUM;
  898.     break;
  899.   case LZXHDR_PACK_NORMAL:
  900.     if(!ai->xai_PrivateClient && !(decr = (struct LZXDecrData *)
  901.     xadAllocVec(sizeof(struct LZXDecrData), MEMF_PUBLIC|MEMF_CLEAR)))
  902.       ret = XADERR_NOMEMORY;
  903.     else
  904.     {
  905.       if(decr)
  906.       {
  907.         decr->ArchivePos = LZXPE(fi)->ArchivePos;
  908.         decr->DataPos = 0;
  909.         decr->shift = -16;
  910.         decr->last_offset = 1;
  911.         decr->source_end = (decr->source = decr->read_buffer + 16384) - 1024;
  912.         decr->pos = decr->destination_end = decr->destination = decr->decrunch_buffer + 258 + 65536;
  913.         decr->pack_size = fi->xfi_Flags & XADFIF_GROUPED ?
  914.         fi->xfi_GroupCrSize : fi->xfi_CrunchSize;
  915.         ai->xai_PrivateClient = decr;
  916.       }
  917.  
  918.       if((i = LZXPE(fi)->DataStart - LZXDD(ai)->DataPos))
  919.     ret = LZXextract(ai, xadMasterBase, i, 0);
  920.     
  921.       if(!ret)
  922.     ret = LZXextract(ai, xadMasterBase, fi->xfi_Size, LZXPE(fi)->CRC);
  923.  
  924.       /* free no longer needed temporary buffer and stuff structure */
  925.       if(ret || !(fi->xfi_Flags & XADFIF_GROUPED) || (fi->xfi_Flags & XADFIF_ENDOFGROUP))
  926.       {
  927.         xadFreeObjectA(ai->xai_PrivateClient, 0);
  928.         ai->xai_PrivateClient = 0;
  929.       }
  930.     }
  931.     break;
  932.   default: ret = XADERR_DECRUNCH; break;
  933.   }
  934.  
  935.   return ret;
  936. }
  937.  
  938. ASM(void) LZX_Free(REG(a0, struct xadArchiveInfo *ai),
  939. REG(a6, struct xadMasterBase *xadMasterBase))
  940. {
  941.   if(ai->xai_PrivateClient) /* decrunch buffer */
  942.   {
  943.     xadFreeObjectA(ai->xai_PrivateClient, 0);
  944.     ai->xai_PrivateClient = 0;
  945.   }
  946. }
  947.  
  948. const struct xadClient LZX_Client = {
  949. NEXTCLIENT, XADCLIENT_VERSION, XADMASTERVERSION, LZX_VERSION, LZX_REVISION,
  950. 10, XADCF_FILEARCHIVER|XADCF_FREEFILEINFO, XADCID_LZX, "LZX",
  951. (BOOL (*)()) LZX_RecogData, (LONG (*)()) LZX_GetInfo,
  952. (LONG (*)()) LZX_UnArchive, (void (*)()) LZX_Free};
  953.  
  954. #endif /* XADASTER_LZX_C */
  955.